package com.example.zhongwangtong_machine_test;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author Jockery
 * @Description:
 * @create 2024-10-12 上午 10:43
 */
@Component
@Slf4j
public class SimpleCacheUtil<K, V> {
    private final ConcurrentHashMap<K, CacheEntry<V>> cache = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    /**
     * 将值放入缓存中，并设置过期时间。
     * @param key 缓存键
     * @param value 缓存值
     * @param ttl 过期时间（秒）
     */
    public void put(K key, V value, long ttl) {
        cache.put(key, new CacheEntry<>(value, System.currentTimeMillis() + ttl * 1000));
    }

    /**
     * 从缓存中获取值。
     * @param key 缓存键
     * @return 缓存值，如果未找到或已过期则返回null
     */
    public V get(K key) {
        CacheEntry<V> entry = cache.get(key);
        if (entry != null && !isExpired(entry)) {
            return entry.getValue();
        } else {
            // 如果过期，则从缓存中移除
            cache.remove(key);
            return null;
        }
    }

    /**
     * 启动定时清理任务。
     */
    public void startCleanupTask(long interval, TimeUnit unit) {
        scheduler.scheduleAtFixedRate(this::cleanupExpiredEntries, 0, interval, unit);
    }

    /**
     * 清理所有已过期的缓存项。
     */
    private void cleanupExpiredEntries() {
        Iterator<Map.Entry<K, CacheEntry<V>>> iterator = cache.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<K, CacheEntry<V>> entry = iterator.next();
            if (isExpired(entry.getValue())) {
                iterator.remove();
            }
        }
    }

    /**
     * 检查缓存项是否已过期。
     * @param entry 缓存项
     * @return 如果已过期返回true，否则返回false
     */
    private boolean isExpired(CacheEntry<V> entry) {
        return entry.getExpirationTime() < System.currentTimeMillis();
    }

    /**
     * 内部类表示缓存条目。
     */
    private static class CacheEntry<V> {
        private final V value;
        private final long expirationTime;

        public CacheEntry(V value, long expirationTime) {
            this.value = value;
            this.expirationTime = expirationTime;
        }

        public V getValue() {
            return value;
        }

        public long getExpirationTime() {
            return expirationTime;
        }
    }
}
